package com.hspedu.tankgame05;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.util.Vector;

//绘图区域
//为了监听键盘事件，实现KeyListener
//为了让子弹不停重绘，需要MyPanel实现Runnable,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener ,Runnable{
    //定义我的坦克
    Hero hero = null;
    //定义敌人坦克,由于考虑到多个敌人和多线程，所以需要放到Vector集合中
    Vector<EnemyTank> enemyTanks = new Vector<>();
    //存放node的Vector，用于恢复坦克信息
    Vector<Node> nodes = new Vector<>();
    //定义Vector,用于存放炸弹
    //当敌方坦克被击中时，加入一个Bomb对象到bombs中
    Vector<Bomb> bombs = new Vector<>();

    int enemySize = 3;

    //定义三张炸弹图片，用于显示炸弹效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;

    public MyPanel(String key) {
        nodes = Record.getNodes();
        //游戏开局将enemyTanks放入到Record中
        Record.setEnemyTanks(enemyTanks);
        hero = new Hero(500,100);//初始化自己的坦克
        hero.setSpeed(5);

        switch (key) {
            case "1"://新游戏
                //初始化敌人位置
                for (int i = 0;i < enemySize;i++) {
                    //创建一个敌人坦克
                    EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
                    //将enemyTanks 设置给 enemyTank
                    enemyTank.setEnemyTanks(enemyTanks);
                    //设置方向
                    enemyTank.setDirect(2);
                    //创建一个敌人线程，让它动起来
                    new Thread(enemyTank).start();
                    //给每个坦克加入子弹,子弹与坦克同向
                    Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
                    enemyTank.shots.add(shot);
                    //启动线程
                    new Thread(shot).start();
                    //加入一个坦克
                    enemyTanks.add(enemyTank);
                }
                break;
            case "2"://继续上局
                //初始化敌人位置
                for (int i = 0;i < nodes.size();i++) {
                    //取出
                    Node node = nodes.get(i);
                    //创建一个敌人坦克
                    EnemyTank enemyTank = new EnemyTank(node.getX(), node.getY());
                    //将enemyTanks 设置给 enemyTank
                    enemyTank.setEnemyTanks(enemyTanks);
                    //设置方向
                    enemyTank.setDirect(node.getDirect());
                    //创建一个敌人线程，让它动起来
                    new Thread(enemyTank).start();
                    //给每个坦克加入子弹,子弹与坦克同向
                    Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
                    enemyTank.shots.add(shot);
                    //启动线程
                    new Thread(shot).start();
                    //加入一个坦克
                    enemyTanks.add(enemyTank);
                }
                break;
            default:
                System.out.println("你的输入有误！");
        }

        //初始化图片对象
        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.png"));
        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.png"));
        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.png"));
    }

    //记录我方击毁的坦克数量
    public void showInfo(Graphics g) {
        //显示我方的成绩
        g.setColor(Color.BLACK);
        Font font = new Font("宋体",Font.BOLD,25);
        g.setFont(font);
        g.drawString("您累计击毁的坦克数",1020,30);
        //绘制敌人坦克
        drawTank(1020,60,g,0,0);
        g.setColor(Color.BLACK);//需要重新更新画笔颜色
        //类方法返回int类型， + “”转成字符串
        g.drawString(Record.getAllEnemyTank() + "",1080,100);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,750);//填充矩形，默认黑色
        showInfo(g);
        if (hero != null && hero.isALive) {
            //画出自己的坦克->封装方法
            drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),1);
        }

        //画出hero子弹->和敌人子弹逻辑一致
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if (shot != null && shot.isALive == true) {
                //g.fill3DRect(hero.shot.x,hero.shot.y,1,1,false);不清晰
                g.draw3DRect(shot.x,shot.y,2,2,false);
            }else {
                //Shot对象无效，从集合中取出
                hero.shots.remove(shot);
            }
        }

        //如果bombs集合中还有bomb，画出
        for (int i = 0; i < bombs.size(); i++) {
            //取出
            Bomb bomb = bombs.get(i);
            //根据当前生命值画出对应的图片
            if (bomb.life > 6) {
                g.drawImage(image1,bomb.x,bomb.y,60,60,this);
            }else if (bomb.life > 3) {
                g.drawImage(image2,bomb.x,bomb.y,60,60,this);
            }else {
                g.drawImage(image3,bomb.x,bomb.y,60,60,this);
            }

            //生命值减少
            bomb.lifeDown();
            //生命值为0，删除
            if (bomb.life == 0) {
                bombs.remove(bomb);
            }
        }

        //画出敌人坦克,遍历Vector
        for(int i = 0;i < enemyTanks.size();i++) {
            //判断当前坦克是否存活
            EnemyTank enemyTank = enemyTanks.get(i);
            if (enemyTank.isALive) {
                //活着才画坦克
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);
                //画敌人子弹
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    Shot shot = enemyTank.shots.get(j);
                    //绘制
                    if (shot != null && shot.isALive == true) {
                        g.draw3DRect(shot.x, shot.y, 2, 2, false);
                    } else {
                        //当子弹不存活时，从Vector中移除
                        enemyTank.shots.remove(shot);
                    }
                }
            }
        }
    }
    //画坦克
    /**
     * x 坦克左上角x坐标
     * y 坦克左上角y坐标
     * g 画笔
     * direct 坦克方向
     * type 坦克类型
     */
    public void drawTank(int x,int y,Graphics g,int direct,int type) {
        //不同类型设置不同颜色
        switch (type) {
            case 0://敌人的坦克
                g.setColor(Color.cyan);
                break;
            case 1://自己的坦克
                g.setColor(Color.yellow);
                break;
        }

        //根据方向绘制坦克
        switch (direct) {
            case 0://表示向上
                g.fill3DRect(x,y,10,60,false);//左边轮子
                g.fill3DRect(x + 30,y,10,60,false);//右边轮子
                g.fill3DRect(x + 10,y + 10,20,40,false);//盖子
                g.fillOval(x + 10,y + 20,20,20);//圆盖
                g.drawLine(x + 20,y + 30,x + 20,y);
                break;
            case 1://表示向右
                g.fill3DRect(x,y,60,10,false);//上边轮子
                g.fill3DRect(x,y + 30,60,10,false);//下边轮子
                g.fill3DRect(x + 10,y + 10,40,20,false);//盖子
                g.fillOval(x + 20,y + 10,20,20);//圆盖
                g.drawLine(x + 30,y + 20,x + 60,y + 20);//炮筒
                break;
            case 2://表示向上
                g.fill3DRect(x,y,10,60,false);//左边轮子
                g.fill3DRect(x + 30,y,10,60,false);//右边轮子
                g.fill3DRect(x + 10,y + 10,20,40,false);//盖子
                g.fillOval(x + 10,y + 20,20,20);//圆盖
                g.drawLine(x + 20,y + 30,x + 20,y + 60);//炮筒
                break;
            case 3://表示向左
                g.fill3DRect(x,y,60,10,false);//上边轮子
                g.fill3DRect(x,y + 30,60,10,false);//下边轮子
                g.fill3DRect(x + 10,y + 10,40,20,false);//盖子
                g.fillOval(x + 20,y + 10,20,20);//圆盖
                g.drawLine(x + 30,y + 20,x,y + 20);//炮筒
                break;
            default:
                System.out.println("暂时不处理");
        }
    }

    //但我们的子弹有多颗时，会出现子弹穿过坦克但没有爆炸
    //原因:hitTank方法只判断了一颗子弹碰到坦克
    //需要遍历子弹集合，每颗子弹判断是否命中
    public void hitEnemyTank() {
        //遍历子弹
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            //判断子弹是否击中坦克
            if (shot != null && shot.isALive) {
                //当自己的子弹还存活
                //遍历所有的敌方坦克
                for (int j = 0; j < enemyTanks.size(); j++) {
                    EnemyTank enemyTank = enemyTanks.get(j);
                    hitTank(hero.shot,enemyTank);
                }
            }
        }
    }

    //判断子弹击中坦克
    public void hitTank(Shot shot,Tank Tank) {
        //shot落到坦克范围内
        switch (Tank.getDirect()) {
            case 0://上
            case 2://右
                if (shot.x > Tank.getX() && shot.x < Tank.getX() + 40
                && shot.y < Tank.getY() + 60 && shot.y > Tank.getY()) {
                    shot.isALive = false;
                    Tank.isALive = false;
                    //敌人生命值为0，删除
                    enemyTanks.remove(Tank);
                    //Tank有可能是Hero，也有可能是EnemyTank
                    //判断，确保确实是EnemyTank
                    if (Tank instanceof EnemyTank) {
                        Record.addAllEnemyTankNum();
                    }
                    //子弹击中坦克
                    //创建Bomb对象,加入到bombs集合中
                    Bomb bomb = new Bomb(Tank.getX(), Tank.getY());
                    bombs.add(bomb);
                }
                break;
            case 1://下
            case 3://左
                if (shot.x > Tank.getX() && shot.x < Tank.getX() + 60
                        && shot.y < Tank.getY() + 40 && shot.y > Tank.getY()) {
                    shot.isALive = false;
                    Tank.isALive = false;
                    //敌人生命值为0，删除
                    enemyTanks.remove(Tank);
                    //Tank有可能是Hero，也有可能是EnemyTank
                    //判断，确保确实是EnemyTank
                    if (Tank instanceof EnemyTank) {
                        Record.addAllEnemyTankNum();
                    }
                    //子弹击中坦克
                    //创建Bomb对象,加入到bombs集合中
                    Bomb bomb = new Bomb(Tank.getX(), Tank.getY());
                    bombs.add(bomb);
                }
                break;
        }
    }

    //判断敌人坦克击中我方坦克
    public void hitHero() {
        //遍历所有坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出敌人坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            //遍历每个坦克的每个子弹
            for (int j = 0; j < enemyTank.shots.size(); j++) {
                //取出子弹
                Shot shot = enemyTank.shots.get(j);
                //判断是否击中
                if (hero.isALive && shot.isALive) {
                    hitTank(shot,hero);
                }
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //处理wasd键按下的情况
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            //改变坦克方向
            hero.setDirect(0);
            //修改坦克坐标 y -= 1
            //hero.setY(hero.getY() - 1); ->写起来麻烦
            if (hero.getY() > 0) {
                hero.moveUp();//封装
            }
        }else if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setDirect(1);
            if (hero.getX() + 60 < 1000) {
                hero.moveRight();
            }
        }else if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setDirect(2);
            if (hero.getY() + 60 < 750) {
                hero.moveDown();
            }
        }else if (e.getKeyCode() == KeyEvent.VK_A){
            hero.setDirect(3);
            if (hero.getX() > 0) {
                hero.moveLeft();
            }
        }

        //如果获取J键,执行发射行为,一次发射一颗子弹
        if (e.getKeyCode() == KeyEvent.VK_J) {
            //System.out.println("开始射击");
//            if (hero.shot == null || hero.shot.isALive == false) {
//                hero.ShotEnemyTank();
//            }
            if (hero.isALive) {
                //发射多颗子弹
                hero.ShotEnemyTank();
            }else return;
        }
        //让面板重绘
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        //每隔100ms,重绘一次游戏区域
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断我方子弹是否击中敌方坦克
            hitEnemyTank();
            //判断敌方子弹是否击中我方坦克
            hitHero();
            this.repaint();
        }
    }
}
